import 'package:flutter/material.dart';

// https://dart.dev/guides/language/language-tour#generics

class GenericPage extends StatefulWidget {
  final Map<String, dynamic> arguments;
  GenericPage({Key key, this.arguments}) : super(key: key);

  @override
  _GenericPageState createState() => _GenericPageState();
}

class _GenericPageState extends State<GenericPage> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: Text('GenericPage'),
        ),
        body: ListView(
          children: <Widget>[
            ListTile(
              title: Text('编码问题及泛型作用'),
              subtitle: Text('''
1, 类, 接口等方法复用;
2, 对不特定类型的支持;
'''),
              onTap: () {
                // 问题 (代码重复)
                returnInt(int num) => num;
                returnString(String string) => string;

                returnInt(18);
                returnString('coder');

                // 解决
                returnValue(value) => value;

                returnValue(18);
                returnValue('coder');
              },
            ),
            Divider(height: 1.0),
            ListTile(
              title: Text('泛型方法'),
              subtitle: Text('T returnValue<T>(T value) => value;'),
              onTap: () {
                T returnValue<T>(T value) => value;
                final num = returnValue<int>(18);
                final name = returnValue<String>('coder');

                print(num);
                print(name);

                // 可以用任意字母 一般为 T
                F fReturnValue<F>(F value) => value;
                fReturnValue(18);
                fReturnValue('coder');
              },
            ),
            Divider(height: 1.0),
            ListTile(
              title: Text('泛型类'),
              subtitle: Text('''
如 List 
e.g.
class Adder<T> {
  List _list = <T>[];
  add(T value) {
    this._list.add(value);
  }

  show() {
    print(this._list);
  }
}'''),
              onTap: () {
                // 不指定类型
                (() {
                  List list = [];
                  list.add(18);
                  list.add('coder');
                  print(list);
                })();

                // 指定类型
                (() {
                  List list = <String>[];
                  // list.add(18); // 运行将报错 type 'int' is not a subtype of type 'String' of 'value'
                  list.add('coder');
                })();

                // Adder<String>
                (() {
                  final adder = Adder<String>(); // 实例化时指定类型
                  adder.add('Akon');
                  // adder.add(18); // 直接报错
                  adder.add('Céline Dion');
                  // adder.add(3); // 直接报错
                  adder.show();
                })();

                // Adder<int>
                (() {
                  final adder = Adder<int>(); // 实例化时指定类型
                  // adder.add('Akon'); // 直接报错
                  adder.add(18);
                  // adder.add('Céline Dion'); // 直接报错
                  adder.add(3);
                  adder.show();
                })();
              },
            ),
            Divider(height: 1.0),
            ListTile(
              title: Text('泛型接口'),
              subtitle: Text('''
实现代码复用及不特定类型支持
abstract class NetTool<T> {
  T download(String url);
  upload(String url, T obj);
}'''),
              onTap: () {
                // SocketTool
                (() {
                  // 上传下载 String 类型
                  (() {
                    final s = SocketTool<String>();
                    s.download('url');
                    s.upload('url', 'coder');
                    // s.upload('url', 12); // 直接报错
                  })();
                  // 上传下载 int 类型
                  (() {
                    final s = SocketTool<int>();
                    s.download('url');
                    // s.upload('url', 'coder'); // 直接报错
                    s.upload('url', 12);
                  })();
                })();

                // HttpTool
                (() {
                  // 上传下载 double 类型
                  (() {
                    final s = HttpTool<double>();
                    s.download('url');
                    s.upload('url', 99.99);
                    // s.upload('url', 'coder'); // 直接报错
                  })();
                  // 上传下载 Image 类型
                  (() {
                    final s = HttpTool<Image>();
                    s.download('url');
                    // s.upload('url', 'coder'); // 直接报错
                    s.upload('url', Image(image: NetworkImage('url')));
                  })();
                })();
              },
            ),
            Divider(height: 1.0),
          ],
        ),
      ),
    );
  }
}

class Adder<T> {
  List _list = <T>[];
  add(T value) {
    this._list.add(value);
  }

  show() {
    print(this._list);
  }
}

abstract class NetTool<T> {
  T download(String url);
  upload(String url, T obj);
}

class SocketTool<T> implements NetTool<T> {
  @override
  T download(String url) {
    // TODO: 怎么获取并创建 T 类型的实例, 以及类型和字符串相互转换
    return null;
  }

  @override
  upload(String url, T obj) {
    print('SocketTool 上传了 ${obj.runtimeType} 类型数据');
  }
}

class HttpTool<T> implements NetTool<T> {
  @override
  T download(String url) {
    return null;
  }

  @override
  upload(String url, T obj) {
    print('HttpTool 上传了 ${obj.runtimeType} 类型数据');
  }
}

// ====================================================================================================
// Generics Restricting
abstract class Couputer {}

class Mac extends Couputer {}

class Windows extends Couputer {}

class Xbox {}

class GenericsRestricting {
  restrictingFunc<T extends Couputer>({T computer}) {}

  testRestricting() {
    final mac = Mac();
    final windows = Windows();
    final xBox = Xbox();

    restrictingFunc(computer: mac);
    restrictingFunc(computer: windows);
    // restrictingFunc(computer: xBox); // 将报错
  }
}
